﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.UI.WebControls;
using Telerik.Web.UI;
using Medianamik.Core;
using Medianamik.Core.Sugar;
using System.ComponentModel;
using System.Web.UI;
using Medianamik.Globalization;

namespace Medianamik.UI.Controls
{
    public class TreeView : RadTreeView
    {
        #region NeedParents Event
        private static readonly object _needSelfAndParentsEvent = new object();
        public event EventHandler<NeedSelfAndParentsEventArgs> NeedSelfAndParents
        {
            add
            {
                Events.AddHandler(_needSelfAndParentsEvent, value);
            }
            remove
            {
                Events.RemoveHandler(_needSelfAndParentsEvent, value);
            }
        }
        protected virtual void OnNeedSelfAndParents(NeedSelfAndParentsEventArgs args)
        {
            var eh = Events[_needSelfAndParentsEvent] as EventHandler<NeedSelfAndParentsEventArgs>;
            if (eh != null)
            {
                eh.Invoke(this, args);
            }
        }

        #endregion

        #region Need Children Event
        private static readonly object _needChildrenEvent = new object();
        public event EventHandler<NeedChildrenEventArgs> NeedChildren
        {
            add
            {
                Events.AddHandler(_needChildrenEvent, value);
            }
            remove
            {
                Events.RemoveHandler(_needChildrenEvent, value);
            }
        }
        protected virtual void OnNeedChildren(NeedChildrenEventArgs args)
        {
            var eh = Events[_needChildrenEvent] as EventHandler<NeedChildrenEventArgs>;
            if (eh != null)
            {
                eh.Invoke(this, args);
            }
        }

        #endregion

        #region Properties

        [Bindable(true)]
        public String CurrentItemValue
        {
            get { return ViewState["CurrentItemValue"] as string; }
            set
            {
                ViewState["CurrentItemValue"] = value;
            }
        }

        [Bindable(true)]
        public String NodeToExpandValue
        {
            get { return ViewState["NodeToExpandValue"] as string; }
            set
            {
                ViewState["NodeToExpandValue"] = value;
            }
        }

        [Bindable(true)]
        public String ConfirmMessage
        {
            get
            {
                object msg = ViewState["ConfirmMessage"];
                if (msg == null || string.IsNullOrEmpty(msg.ToString()))
                    return Translator.Translate("Medianamik_ContentManagement", "DefaultNavigateNodeMessage");
                return msg.ToString();
            }
            set
            {
                ViewState["ConfirmMessage"] = value;
            }
        }

        [Bindable(true)]
        public bool MustConfirm
        {
            get
            {
                if (ViewState["MustConfirm"] == null)
                    return default(bool);
                return (bool)ViewState["MustConfirm"];
            }
            set
            {
                ViewState["MustConfirm"] = value;
            }
        }

        #endregion

        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);
            base.NodeExpand += TreeView_NodeExpand;
            base.Page.LoadComplete += Page_LoadComplete;
            this.LoadingMessage = Translator.Translate("medianamik_controls", "treeview_loading_message");
        }

        void Page_LoadComplete(object sender, EventArgs e)
        {
            var selfAndParents = new List<ITreeItem>();
            //Trouver le Noeud à selectionner
            var currentNode = CurrentItemValue == null
            ? default(RadTreeNode)
            : FindNodeByValue(CurrentItemValue);
            if (currentNode == null)
            {
                //Charger la hierarchie parents
                var selfAndParentEventArgs = new NeedSelfAndParentsEventArgs(CurrentItemValue);
                OnNeedSelfAndParents(selfAndParentEventArgs);
                selfAndParents.AddRange(selfAndParentEventArgs.Items);
            }

            selfAndParents.Sort((n1, n2) => (n1.Depth ?? 0).CompareTo(n2.Depth ?? 0));
            var parentNodeCol = this.Nodes;
            foreach (var treeItem in selfAndParents)
            {
                //Trouver le Noeud
                RadTreeNode node = base.FindNodeByValue(treeItem.Value);
                if (node == null)
                {
                    node = BuildTreeNode(treeItem);
                    parentNodeCol.Add(node);

                }
                if (node.Nodes.Count == 0)
                {
                    //Charger les enfants
                    var args = new NeedChildrenEventArgs(treeItem.Value);
                    OnNeedChildren(args);
                    node.Nodes.AddRange(args.ChildNodes.Select(n => BuildTreeNode(n)));
                }
                parentNodeCol = node.Nodes;
            }


            if (CurrentItemValue != null)
            {
                var node = base.FindNodeByValue(CurrentItemValue);
                if (node != null)
                {
                    if (node.Nodes.Count == 0)
                    {
                        //Charger les enfants
                        var args = new NeedChildrenEventArgs(CurrentItemValue);
                        OnNeedChildren(args);
                        node.Nodes.AddRange(args.ChildNodes.Select(n => BuildTreeNode(n)));
                    }
                    node.Selected = true;
                    node.Expanded = true;
                    node.ExpandMode = TreeNodeExpandMode.ClientSide;
                    var parentNode = node.ParentNode;
                    while (parentNode != null)
                    {
                        //Désactiver le callback car les noeuds sont déjà chargés
                        parentNode.Expanded = true;
                        parentNode.ExpandMode = TreeNodeExpandMode.ClientSide;
                        parentNode = parentNode.ParentNode;
                    }
                }
            }

            if (NodeToExpandValue != null)
            {
                var node = base.FindNodeByValue(NodeToExpandValue);
                if (node != null)
                {
                    if (node.Nodes.Count == 0)
                    {
                        //Charger les enfants
                        var args = new NeedChildrenEventArgs(NodeToExpandValue);
                        OnNeedChildren(args);
                        node.Nodes.AddRange(args.ChildNodes.Select(n => BuildTreeNode(n)));
                    }
                }
                node.Expanded = true;
                node.ExpandMode = TreeNodeExpandMode.ClientSide;
            }

            if (MustConfirm)
            {
                this.OnClientNodeClicking = "ProcessClientClick";
            }
        }

        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);
            if (MustConfirm)
            {
                ScriptManager.GetCurrent(Page).Services.Add(new ServiceReference("/Medianamik/Services/LockWebService.asmx"));
                ScriptManager.RegisterClientScriptBlock(this, typeof(TreeView), "Confirm",
                    String.Concat("function ProcessClientClick(sender, eventArgs) {",
                                        "eventArgs.set_cancel(!confirm('" + ConfirmMessage + "'));",
                                    "}"),
                    true);
            }
        }

        protected void TreeView_NodeExpand(object sender, RadTreeNodeEventArgs e)
        {
            NeedChildrenEventArgs args = new NeedChildrenEventArgs(e.Node.Value);
            OnNeedChildren(args);

            e.Node.Nodes.AddRange(args.ChildNodes.Select(n => BuildTreeNode(n)));
        }

        protected RadTreeNode BuildTreeNode(ITreeItem pItem)
        {
            var node = new RadTreeNode(pItem.Text, pItem.Value, pItem.NavigateUrl);
            
            if(!string.IsNullOrEmpty( pItem.ImageUrl ))
            {
                node.ImageUrl = pItem.ImageUrl;
            }

            if ((pItem.HasChildren ?? true))
            {
                node.ExpandMode = TreeNodeExpandMode.ServerSideCallBack;
            }

            node.Enabled = pItem.Enabled ?? true;

            if (!pItem.UIEnabled.GetValueOrDefault(true))
            {
                node.Category = "Disabled";
                node.CssClass += " rtDisabled";
                node.HoveredCssClass = "rtDisabled";
                node.SelectedCssClass = "rtDisabled";
            }

            return node;
        }
    }


    public class NeedChildrenEventArgs : EventArgs
    {
        public NeedChildrenEventArgs(string pParentValue)
        {
            ParentValue = pParentValue;
        }

        public string ParentValue { get; private set; }

        private List<ITreeItem> _childNodes = new List<ITreeItem>();
        public List<ITreeItem> ChildNodes
        {
            get { return _childNodes; }
        }
    }

    public class NeedSelfAndParentsEventArgs : EventArgs
    {
        public NeedSelfAndParentsEventArgs(string pItemValue)
        {
            ItemValue = pItemValue;
        }

        public string ItemValue { get; private set; }

        private List<ITreeItem> _items = new List<ITreeItem>();
        public List<ITreeItem> Items
        {
            get { return _items; }
        }
    }
}
